package org.example.bingfa.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * author:
 * Date:2024/3/3112:44
 **/
public class Test {

    public static void main(String[] args) {
        //同时 先用await暂停住  然后countDown()一起释放
//        test1();

        //顺序
        //1.使用volatile 保证一个变量的可见性  然后判断变量
        //2.定义三个CountDownLatch  a唤醒b  b唤醒c c唤醒a
//        test2();
        test22();

        //交叉
        //使用Condition 实现线程通信
        //void signal()：唤醒一个等待在condition上的线程，将该线程从等待队列中转移到同步队列中，
        // 如果在同步队列中能够竞争到Lock则可以从等待方法中返回
        //当前线程进入等待状态，如果其他线程调用condition的signal或者signalAll方法
        // 并且当前线程获取Lock从await方法返回，
        // 如果在等待状态中被中断会抛出被中断异常；
        test3();

    }

    public static void test1() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        CountDownLatch countDownLatch = new CountDownLatch(1);

        executorService.submit(()->{
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("线程A执行，执行时间：" + System.currentTimeMillis());
        });

        executorService.submit(()->{
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("线程B执行，执行时间：" + System.currentTimeMillis());
        });

        executorService.submit(()->{
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("线程C执行，执行时间：" + System.currentTimeMillis());
        });

        countDownLatch.countDown();


    }

    private static volatile int count = 0;

    public static void test2() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        executorService.submit(() -> {
            while (true) {
                if (count == 0) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("A - " + i);
                    }

                    count = 1;
                    break;
                }
            }
        });

        executorService.submit(() -> {
            while (true) {
                if (count == 1) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("B - " + i);
                    }

                    count = 2;
                    break;
                }
            }
        });
        executorService.submit(() -> {
            while (true) {
                if (count == 2) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("C - " + i);
                    }

                    count = 3;
                    break;
                }
            }
        });

    }

    public static void test22() {
        ExecutorService executorService = Executors.newCachedThreadPool();
        CountDownLatch aLatch = new CountDownLatch(1);
        CountDownLatch bLatch = new CountDownLatch(1);
        CountDownLatch cLatch = new CountDownLatch(1);

        executorService.submit(() -> {
            try {
                aLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            for (int i = 0; i < 10; i++) {
                System.out.println("A - " + i);
            }

            bLatch.countDown();
        });

        executorService.submit(() -> {
            try {
                bLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            for (int i = 0; i < 10; i++) {
                System.out.println("B - " + i);
            }

            cLatch.countDown();
        });

        executorService.submit(() -> {
            try {
                cLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            for (int i = 0; i < 10; i++) {
                System.out.println("C - " + i);
            }
        });

        aLatch.countDown();
    }


    private static final ReentrantLock lock = new ReentrantLock();
    private static Condition c1 = lock.newCondition();
    private static Condition c2 = lock.newCondition();
    private static Condition c3 = lock.newCondition();


    public static void test3() {
        new Thread(() -> {
            try {
                lock.lock();

                for (int i = 0; i < 10; i++) {
                    System.out.println("A - " + i);
                    c2.signal();
                    c1.await();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();

        new Thread(() -> {
            try {
                lock.lock();

                for (int i = 0; i < 10; i++) {
                    System.out.println("B - " + i);
                    c3.signal();
                    c2.await();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();

        new Thread(() -> {
            try {
                lock.lock();

                for (int i = 0; i < 10; i++) {
                    System.out.println("C - " + i);
                    c1.signal();
                    c3.await();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }).start();
    }
}
